#include "StdAfx.h"
#include "IrrCamera.h"

#include "../Kernel.h"

extern irr::IrrlichtDevice*  g_IrrDevice;
extern Kernel* g_kernel;

unsigned int ICamera::CAMERA_ID = 0;

IrrCamera::IrrCamera(void) : ICamera()
{
    m_IrrCamera   = NULL;
    m_IrrSceneMng = NULL;
}

IrrCamera::~IrrCamera(void)
{
}

/** Initialize the camera */
bool IrrCamera::Init()
{
    static bool firstCamera = true;

    if ( g_IrrDevice )
    {
        m_IrrSceneMng = g_IrrDevice->getSceneManager();
        if ( firstCamera )
        {
            m_IrrCamera = m_IrrSceneMng->addCameraSceneNodeFPS();
            m_IrrCamera->setInputReceiverEnabled( true );
            SetMainCamera();
            firstCamera = false;

        } else {
            m_IrrSceneMng->addCameraSceneNodeFPS();
            m_mainCamera = false;
        }
        return true;
    }
    else
    {
        g_kernel->LPrintf( "ERROR:: Could not initialize a camera, Irrlicht Device not Found!" );
    }
    return false;
}

/** Update the camera to another location if needed */
void IrrCamera::Update(float dt)
{

}

/** Point the camera at a location */
void IrrCamera::LookAt( const MVector3f &pos )
{
    m_IrrCamera->setTarget( pos );
}

/** Move the Camera over time to this new location, multiplied by the speed var */
void IrrCamera::MoveTo( const MVector3f &dest )
{
    m_IrrCamera->setPosition( dest );       // might need to change
}

/** Shake the camera for a duration and a velocity */
void IrrCamera::Shake( float time, float magnitude )
{

}

/** Test to see if this rectangle intersects with the viewport */
bool IrrCamera::Contains( const MAABBox3f &r  )
{
    return m_IrrCamera->getBoundingBox().intersectsWithBox( r );
}

/** Test to see if this point intersects with the viewport */
bool IrrCamera::Contains( const MVector3f &v )
{
    return m_IrrCamera->getBoundingBox().isPointInside( v );
}

/** Get the Position of the camera (world relative) */
MMatrix4x4f IrrCamera::GetProjectionMat() const
{
    return m_IrrCamera->getProjectionMatrix();
}
/** Sets the new position, also recalculates the viewport properly */
void IrrCamera::SetProjectionMat( const MMatrix4x4f &m )
{
    m_IrrCamera->setProjectionMatrix( m );
}

/** Set the up vector */
void IrrCamera::SetUpVector( const MVector3f &v ) 
{
    m_IrrCamera->setUpVector( v );
}
MVector3f IrrCamera::GetUpVector() const
{
    return /*(MVector3f)*/m_IrrCamera->getUpVector();
}

/** Set the FOV */
void IrrCamera::SetFOV ( float f )
{
    m_IrrCamera->setFOV( f );
}

float IrrCamera::GetFOV() const
{
    return m_IrrCamera->getFOV();
}

/** Set the aspect ration */
void IrrCamera::SetAspectRatio( float f )
{
    m_IrrCamera->setAspectRatio( f );
}

float IrrCamera::GetAspectRation() const
{
    return m_IrrCamera->getAspectRatio();
}

/** Set the dimensions of the camera */
void IrrCamera::SetFrustum(const MFrustum &f )  // TODO
{
    MAABBox3f frust = m_IrrCamera->getViewFrustum()->getBoundingBox();
    //m_IrrCamera->setFarValue( frust.MaxEdge.x );
}

const MFrustum* IrrCamera::GetFrustum() const
{
    return m_IrrCamera->getViewFrustum();
}

/** Set to be the main camera */
void IrrCamera::SetMainCamera()
{
    if( m_IrrSceneMng )
    {
        if ( m_IrrCamera ) {
            m_IrrSceneMng->setActiveCamera( m_IrrCamera );
            m_mainCamera = true;
        } else
            g_kernel->LPrintf( "WARNING:: Trying to set a Null main camera!" );
    } else  g_kernel->LPrintf( "WARNING:: No scene to add camera to!" );
}